001    /**
002     * Java Gui Builder - A library to build GUIs using an XML file.
003     * Copyright 2002, 2003 (C) François Beausoleil
004     *
005     * This library is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU Lesser General Public
007     * License as published by the Free Software Foundation; either
008     * version 2.1 of the License, or (at your option) any later version.
009     *
010     * This library is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013     * Lesser General Public License for more details.
014     *
015     * You should have received a copy of the GNU Lesser General Public
016     * License along with this library; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018     */
019    
020    package jgb;
021    
022    import jgb.builder.JgbEntityResolver;
023    import org.xml.sax.Attributes;
024    import org.xml.sax.InputSource;
025    import org.xml.sax.SAXException;
026    import org.xml.sax.SAXParseException;
027    import org.xml.sax.helpers.DefaultHandler;
028    
029    import javax.xml.parsers.ParserConfigurationException;
030    import javax.xml.parsers.SAXParser;
031    import javax.xml.parsers.SAXParserFactory;
032    import java.io.FileReader;
033    import java.io.IOException;
034    import java.io.PrintWriter;
035    
036    /**
037     * Validates a file using it's specified DTD.
038     * <p>
039     * This tool simply parses the first argument in a validating XML parser.
040     * This detects any gross problems with the file (missing tags, missing
041     * required attributes, wrong attribute values, etc.).
042     * </p>
043     * <h2>Usage</h2>
044     * <p>
045     * Simply run the following:
046     * </p>
047     * <pre>
048     * java jgb.ValidateFile <em>path/to/xml-file</em>
049     * </pre>
050     * <p>
051     * This tool may be used to validate <em>any</em> file, not just JGB XML files,
052     * as the tool is not specifically geared towards that.
053     * </p>
054     * @since 0.1a
055     * @author Francois Beausoleil, <a href="mailto:fbos@users.sourceforge.net">fbos@users.sourceforge.net</a>
056     */
057    public class ValidateFile extends DefaultHandler {
058        private static final JgbEntityResolver JGB_ENTITY_RESOLVER = new JgbEntityResolver();
059    
060        private PrintWriter logWriter;
061    
062        private int level;
063    
064        private int warnings;
065        private int errors;
066    
067        ///CLOVER:OFF
068        /**
069         * Parses the file passed as the first argument.
070         * @param args The arguments that were on the command line.
071         * @throws Exception If an exception is thrown while parsing the document.
072         */
073        public static void main(String[] args) throws Exception {
074            if (args.length != 1) {
075                System.err.println("Usage:  java jgb.examples.ValidateFile <xml file>");
076                System.err.println("\tValidates that <xml file> is valid and conforms to it's DTD.");
077                System.exit(1);
078            }
079    
080            final ValidateFile validator = new ValidateFile();
081            final InputSource source = new InputSource(new FileReader(args[0]));
082            validator.validate(source);
083        }
084        ///CLOVER:ON
085    
086        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
087            logWriter.print(levelAsSpaces() + "<" + qName);
088            final String elementId = attributes.getValue("id");
089            if (null != elementId) {
090                logWriter.println(" id='" + elementId + "'>");
091            } else {
092                logWriter.println(">");
093            }
094            level++;
095        }
096    
097        public void endElement(String uri, String localName, String qName)
098                throws SAXException {
099            level--;
100            logWriter.println(levelAsSpaces() + "</" + qName + ">");
101        }
102    
103        public void warning(SAXParseException e) throws SAXException {
104            warnings++;
105            printException("WARNING", e);
106        }
107    
108        public void error(SAXParseException e) throws SAXException {
109            errors++;
110            printException("ERROR", e);
111        }
112    
113        public void fatalError(SAXParseException e) throws SAXException {
114            errors++;
115            printException("FATAL", e);
116        }
117    
118        private void printException(String level, SAXParseException e) {
119            logWriter.print(level);
120            logWriter.print(":  ");
121            logWriter.println("Public ID: " + e.getPublicId()
122                    + ", System ID: " + e.getSystemId()
123                    + ", Line: " + e.getLineNumber());
124            logWriter.println(e.getLocalizedMessage());
125        }
126    
127        private String levelAsSpaces() {
128            StringBuffer buf = new StringBuffer();
129            for (int i = 0; i < level; i++) {
130                buf.append("  ");
131            }
132    
133            return buf.toString();
134        }
135    
136        public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
137            try {
138                logWriter.println("Resolving " + publicId + "...");
139                return JGB_ENTITY_RESOLVER.resolveEntity(publicId, systemId);
140            } catch (IOException e) {
141                throw new SAXException(e);
142            }
143        }
144    
145        public void setReportStream(PrintWriter logWriter) {
146            this.logWriter = logWriter;
147        }
148    
149        public void validate(InputSource source) throws SAXException, ParserConfigurationException, IOException {
150            SAXParserFactory factory = SAXParserFactory.newInstance();
151            factory.setValidating(true);
152            factory.setNamespaceAware(false);
153            SAXParser parser = factory.newSAXParser();
154            parser.parse(source, this);
155    
156            if (warnings > 0 || errors > 0) {
157                logWriter.println(warnings + " warnings and "
158                        + errors + " errors were encountered during "
159                        + "parsing.  Messages should have been provided.");
160            } else {
161                logWriter.println("The file is valid and conforming");
162            }
163        }
164    }